
import random
import VarGlobales
import RuntimeError

class Visitor:

    def __init__(self):
        pass

    def _visitList(self, list):
        last = None
        for i in list:
            last = i.accept(self)
        return last
    
    def visit(self, node):
        return node.accept(self)
    

class ASTGenCode(Visitor):
    def __init__(self):
        Visitor.__init__(self)
        
        self.CodeIn = ""
        
        self.nvars = {}
        self.nomVar = 0
        
        self.netiquetas = {}
        
        self.numCicloPara=0
        self.numFinPara=0
        self.numCicloMientras=0
        self.numFinMientras=0
        self.numCicloRepetir=0
        self.numFinRepetir=0
        self.numSi=0
        self.numSino=0
        self.numFinSi=0
        
    def GetCodeIn(self):
        return self.CodeIn
        
    def ConvToInst(self,tipo, valor):
        aux=tipo<<35
        if tipo==0:
            aux = aux | valor
        elif tipo==1:
            if valor<0:
                aux=aux | 17179869184
                valor=-valor
            aux=aux|(valor<<14)
        elif tipo==2:
            valor = round(valor,5)  #redondeo
            if valor<0:
                aux=aux | 17179869184
                valor=-valor
            ne=int(valor)                       #parte entera
            nd=int(str(valor).split(".")[1])    #parte decimal
            aux=aux|(ne<<14)
            aux=aux|nd
        elif tipo==3:
                aux=aux|(valor<<14)
        elif tipo==4:
            aux = aux | valor
        elif tipo==19:
            aux=aux|valor   #Averiguar memoria fpga
        elif tipo==20:
            aux=aux|valor
        elif tipo==21:
            aux=aux|valor
        return aux
    
    def TraducirEtiquetas(self):
        netiquetas = {}
        aux = self.CodeIn.splitlines()
        linea=0
        for i in aux:
            val=i.split()
            if val[-1][len(val[-1])-1]==':' and len(val)==1: #tipo 24
                netiquetas[val[-1]]=linea
                aux[linea] = self.ConvToInst(24, 0)
            elif val[0]=='jumpFalse':   #tipo 19
                etiqueta=val[-1]
                lineaaux=linea+1
                actual=aux[lineaaux]
                while(actual!=etiqueta):
                    lineaaux+=1
                    actual=aux[lineaaux]
                aux[linea] = self.ConvToInst(19, lineaaux)
            elif val[0] in 'goto':  #tipo 20
                if netiquetas.has_key(val[-1]):
                    aux[linea] = self.ConvToInst(20, netiquetas[val[-1]])
                else:
                    etiqueta=val[-1]
                    lineaaux=linea+1
                    actual=aux[lineaaux]
                    while(actual!=etiqueta):
                        lineaaux+=1
                        actual = aux[lineaaux]
                    aux[linea] = self.ConvToInst(20, lineaaux)
            elif val[0] in 'Call':  #tipo 21
                if netiquetas.has_key(val[-1]):
                    aux[linea] = self.ConvToInst(21, netiquetas[val[-1]])
                else:
                    etiqueta=val[-1]
                    lineaaux=linea+1
                    actual=aux[lineaaux]
                    while(actual!=etiqueta):
                        lineaaux+=1
                        actual=aux[lineaaux]
                    netiquetas[actual]=lineaaux
                    aux[linea] = self.ConvToInst(21, lineaaux)
            linea+=1
        self.CodeIn=""
        for i in aux:
            self.CodeIn+=str(i)+"\n"
    
    def GenLabelCicloPara(self):
        self.numCicloPara+=1
        return "para%s:" % self.numCicloPara

    def GenLabelFinPara(self):
        self.numFinPara+=1
        return "finPara%s:" % self.numFinPara
    
    def GenLabelCicloMientras(self):
        self.numCicloMientras+=1
        return "Mientras%s:" % self.numCicloMientras
    
    def GenLabelFinMientras(self):
        self.numFinMientras+=1
        return "finMientras%s:" % self.numFinMientras
    
    def GenLabelCicloRepetir(self):
        self.numCicloRepetir+=1
        return "repetir%s:" % self.numCicloRepetir
    
    def GenLabelFinRepetir(self):
        self.numFinRepetir+=1
        return "finRepetir%s:" % self.numFinRepetir
    
    def GenLabelSi(self):
        self.numSi+=1
        return "si%s:" % self.numSi
    
    def GenLabelSino(self):
        self.numSino+=1
        return "sino%s:" % self.numSino
    
    def GenLabelFinSi(self):
        self.numFinSi+=1
        return "finSi%s:" % self.numFinSi
    
    def GenName(self):
        RandomName = ""
        for i in range(0,20):
            RandomName += str(chr(random.randint(65,90)))
        return RandomName
    
    def BuscarFuncion(self, id, NumArgumentos, node):
        for i in VarGlobales.ListaFunciones:
            if i.id.nombre == id:
                if i.ListaArgumentos != None and len(i.ListaArgumentos.lista) == NumArgumentos:
                    return
                elif i.ListaArgumentos == None and NumArgumentos == 0:
                    return
                else:
                    raise RuntimeError.RuntimeError("Linea %d: Los parametros del llamado no coinciden con los de la funcion" % (0 if node.linea - VarGlobales.Lresta < 0 else node.linea - VarGlobales.Lresta))
        raise RuntimeError.RuntimeError("Linea %d: La funcion no ha sido declarada" % (0 if node.linea - VarGlobales.Lresta < 0 else node.linea - VarGlobales.Lresta))       
        
                      
    def vPrograma(self, node):
        node.lista.accept(self)
        
    def vLista(self, node):
        for i in node.lista:
            i.accept(self)
            
    def vListaInstrucciones(self, node):
        for i in node.lista:
            i.accept(self)
            
    def vListaParametros(self, node):
        for i in node.lista:
            i.accept(self)
            
    def vListaArgumentos(self, node):
        node.lista.reverse()
        for i in node.lista:
            if self.nvars.has_key(i.nombre):
                self.CodeIn += "%s\n" % self.ConvToInst(4, self.nvars[i.nombre])
            else:
                self.nvars[i.nombre] = self.nomVar
                self.CodeIn += "%s\n" % self.ConvToInst(4, self.nomVar)
                self.nomVar += 1
    
    def vListaFunciones(self, node):
        for i in node.lista:
            i.accept(self)
            
    def vprocedimiento(self, node):
        self.CodeIn += "%s:\n" % node.id.nombre
        #VarGlobales.CodeIn+="%s: \n"%VarGlobales.ConvToInst(22, 0)
        #VarGlobales.netiquetas[self.id.nombre]=VarGlobales.Linea
        if node.ListaArgumentos != None:
            node.ListaArgumentos.accept(self)
        node.bloque.accept(self)
        #VarGlobales.CodeIn+="finfuncion: \n"
        self.CodeIn += "%s\n" % self.ConvToInst(23, 0)
        self.nvars.clear()
        self.nomVar = 0
        
    def vbloque(self, node):
        node.bloque.accept(self)
        
    def vInstruccionNormal(self, node):
        node.expr.accept(self)
        if node.tipo in ['avanzar','av']:
            self.CodeIn += "%s\n" % self.ConvToInst(25, 0)
        elif node.tipo in ['retroceder','rt']:
            self.CodeIn += "%s\n" % self.ConvToInst(26, 0)
        elif node.tipo in ['girarderecha','gd']:
            self.CodeIn += "%s\n" % self.ConvToInst(27, 0)
        elif node.tipo in ['girarizquierda','gi']:
            self.CodeIn += "%s\n" % self.ConvToInst(28, 0)
        elif node.tipo in ['escribe']:
            self.CodeIn += "%s\n" % self.ConvToInst(32, 0)
            
    def vInstruccionSimple(self, node):
        if node.tipo in ['borrarpantalla','bo']:
            self.CodeIn += "%s\n" % self.ConvToInst(29, 0)
        elif node.tipo in ['bajarpluma','bp']:
            self.CodeIn += "%s\n" % self.ConvToInst(30, 0)
        elif node.tipo in ['subirpluma','sp']:
            self.CodeIn += "%s\n" % self.ConvToInst(31, 0)
        elif node.tipo in ['alto','al']:
            self.CodeIn += "%s\n" % self.ConvToInst(33, 0)
            
    def vLLamada(self, node): 
        NumArgumentos = 0
        if node.parametros != None:
            node.parametros.accept(self)
            NumArgumentos = len(node.parametros.lista)
        self.BuscarFuncion(node.id.nombre, NumArgumentos, node)
        self.CodeIn += "Call %s:\n" % node.id.nombre
        #VarGlobales.CodeIn+="Call %s \n"%VarGlobales.ConvToInst(19, VarGlobales.netiquetas[self.id.nombre])
   
    def vInstruccionSI(self, node):
        node.condicion.accept(self)
        sino = self.GenLabelSino()
        finsi = self.GenLabelFinSi()
        if node.bloque2 != None:
            self.CodeIn += "jumpFalse %s\n" % sino
            node.bloque1.accept(self)
            self.CodeIn += "goto %s\n" % finsi
            self.CodeIn += "%s\n" % sino
            node.bloque2.accept(self)
            self.CodeIn += "%s\n" % finsi
        else:
            self.CodeIn += "jumpFalse %s\n" % finsi
            node.bloque1.accept(self)
            self.CodeIn += "%s\n" % finsi
            
    def vCicloRepetir(self, node):
        repetir = self.GenLabelCicloRepetir()
        fin = self.GenLabelFinRepetir()
        #VarGlobales.CodeIn+="pushe %s\n"%"0"
        self.CodeIn += "%s\n" % self.ConvToInst(1, 0)
        #VarGlobales.CodeIn+="= %s\n"%"variable_2010_2011_repetir"
        nv = self.GenName()
        self.nvars[nv] = self.nomVar
        self.CodeIn += "%s\n" % self.ConvToInst(4, self.nomVar)
        self.nomVar += 1
        self.CodeIn += "%s\n" % repetir
        #VarGlobales.CodeIn+="pushv %s\n"%"variable_2010_2011_repetir"
        self.CodeIn += "%s\n" % self.ConvToInst(0, self.nvars[nv])
        node.expr.accept(self)
        #VarGlobales.CodeIn+="<\n"
        self.CodeIn += "%s\n" % self.ConvToInst(10, 0)
        self.CodeIn += "jumpFalse %s\n" % fin
        node.bloque.accept(self)
        #VarGlobales.CodeIn+="pushv %s\n"%"variable_2010_2011_repetir"
        self.CodeIn += "%s\n" % self.ConvToInst(0, self.nvars[nv])
        #VarGlobales.CodeIn+="pushe %s\n"%"1"
        self.CodeIn += "%s\n" % self.ConvToInst(1, 1)
        #VarGlobales.CodeIn+="+\n"
        self.CodeIn += "%s\n" % self.ConvToInst(5, 0)
        #VarGlobales.CodeIn+="= %s\n"%"variable_2010_2011_repetir"
        self.CodeIn += "%s\n" % self.ConvToInst(4, self.nvars[nv])
        self.CodeIn += "goto %s\n" % repetir
        self.CodeIn += "%s\n" % fin
        
    def vCicloPara(self, node):
        para = self.GenLabelCicloPara()
        fin = self.GenLabelFinPara()
        node.expr1.accept(self)
        #VarGlobales.CodeIn+="= %s \n"%self.id.nombre
        if self.nvars.has_key(node.id.nombre):
            self.CodeIn += "%s\n" % self.ConvToInst(4, self.nvars[node.id.nombre])
        else:
            self.nvars[node.id.nombre] = self.nomVar
            self.CodeIn += "%s\n" % self.ConvToInst(4, self.nomVar)
            self.nomVar += 1
        self.CodeIn += "%s\n" % para
        #VarGlobales.CodeIn+="pushv %s \n"%self.id.nombre
        self.CodeIn += "%s\n" % self.ConvToInst(0, self.nvars[node.id.nombre])
        node.hasta.accept(self)
        #VarGlobales.CodeIn+="<=\n"
        self.CodeIn += "%s\n" % self.ConvToInst(12, 0)
        self.CodeIn += "jumpFalse %s\n" % fin
        node.bloque.accept(self)
        #VarGlobales.CodeIn+="pushv %s \n"%self.id.nombre
        self.CodeIn += "%s\n" % self.ConvToInst(0, self.nvars[node.id.nombre])
        node.incremento.accept(self)
        #VarGlobales.CodeIn+="+\n"
        self.CodeIn += "%s\n" % self.ConvToInst(5, 0)
        #VarGlobales.CodeIn+="= %s \n"%self.id.nombre
        self.CodeIn += "%s\n" % self.ConvToInst(4, self.nvars[node.id.nombre])
        self.CodeIn += "goto %s\n" % para
        self.CodeIn += "%s\n" % fin
        
    def vInstruccionMientras(self, node):
        mientras = self.GenLabelCicloMientras()
        fin = self.GenLabelFinMientras()
        self.CodeIn += "%s\n" % mientras
        node.condicion.accept(self)
        self.CodeIn += "jumpFalse %s\n" % fin
        node.bloque.accept(self)
        self.CodeIn += "goto %s\n" % mientras
        self.CodeIn += "%s\n" % fin
        
    def vAsignacion(self, node):
        node.expr.accept(self)
        if self.nvars.has_key(node.id.nombre):
            self.CodeIn = self.CodeIn + "%s\n" % self.ConvToInst(4, self.nvars[node.id.nombre])
        else:
            self.nvars[node.id.nombre] = self.nomVar
            self.CodeIn = self.CodeIn + "%s\n" % self.ConvToInst(4, self.nomVar)
            self.nomVar += 1
        #VarGlobales.CodeIn=VarGlobales.CodeIn+"= %s \n"%self.id.nombre
        
    def vRetorno(self, node):
        node.expr.accept(self)
        self.CodeIn += "%s\n" % self.ConvToInst(22, 0)
        
    def vOpBinaria(self, node):
        node.izq.accept(self)
        node.der.accept(self)
        if node.Op == '+':
            self.CodeIn += "%s\n" % self.ConvToInst(5, 0)
        elif node.Op == '-':
            self.CodeIn += "%s\n" % self.ConvToInst(6, 0)
        elif node.Op == '*':
            self.CodeIn += "%s\n" % self.ConvToInst(7, 0)
        elif node.Op == '/':
            self.CodeIn += "%s\n" % self.ConvToInst(8, 0)
        elif node.Op == '<':
            self.CodeIn += "%s\n" % self.ConvToInst(10, 0)
        elif node.Op == '>':
            self.CodeIn += "%s\n" % self.ConvToInst(11, 0)
        elif node.Op == '<=':
            self.CodeIn += "%s\n" % self.ConvToInst(12, 0)
        elif node.Op == '>=':
            self.CodeIn += "%s\n" % self.ConvToInst(13, 0)
        elif node.Op == '==':
            self.CodeIn += "%s\n" % self.ConvToInst(14, 0)
        elif node.Op == '!=':
            self.CodeIn += "%s\n" % self.ConvToInst(15, 0)
        elif node.Op == 'y':
            self.CodeIn += "%s\n" % self.ConvToInst(16, 0)
        elif node.Op == 'o':
            self.CodeIn += "%s\n" % self.ConvToInst(17, 0)
            
    def vOpUnaria(self, node):
        node.expr.accept(self)
        if node.Op == '-':
            self.CodeIn += "%s\n" % self.ConvToInst(9, 0)
        if node.Op == '!':
            self.CodeIn += "%s\n" % self.ConvToInst(18, 0)
            
    def vId(self, node):
        self.CodeIn+="%s\n" % self.ConvToInst(0, self.nvars[node.nombre])
        
    def vnumeroEntero(self, node):
        self.CodeIn += "%s\n" % self.ConvToInst(1, node.numero)
        
    def vnumeroFlotante(self, node):
        self.CodeIn += "%s\n" % self.ConvToInst(2, node.numero)
        
    def vBooleano(self, node):
        if node.tipo == 'falso':
            self.CodeIn += "%s\n" % self.ConvToInst(3, 0)
        else:
            self.CodeIn += "%s\n" % self.ConvToInst(3, 1)
            
class ASTPrint(Visitor):
    def __init__(self):
        Visitor.__init__(self)
        
        self.n = 0
        
        self.arbol="digraph{"
    
    def id(self):
        self.n += 1
        return self.n
    
    
    
    def vPrograma(self, node):
        aux = self.id()
        self.arbol += "n" + str(aux) + "[label=Programa, shape=box];\n\t"
        l = node.lista.accept(self)
        self.arbol += "n" + str(aux) + "->" + "n" + str(l) + ";\n\t"
        
    def vLista(self, node):
        aux = self.id()
        self.arbol += "n" + str(aux) + "[label=\"Lista instrucciones\", shape=box];\n\t"
        for i in node.lista:
            nx = i.accept(self)
            self.arbol += "n" + str(aux) + "->" + "n" + str(nx) + ";\n\t"
        return aux
            
    def vListaInstrucciones(self, node):
        aux = self.id()
        self.arbol += "n" + str(aux) + "[label=\"Lista instrucciones\", shape=box];\n\t"
        for i in node.lista:
            nx = i.accept(self)
            self.arbol += "n" + str(aux) + "->" + "n" + str(nx) + ";\n\t"
        return aux
            
    def vListaParametros(self, node):
        aux = self.id()
        self.arbol += "n" + str(aux) + "[label=\"Lista Parametros\, shape=box];\n\t"
        for i in node.lista:
            nx = i.accept(self)
            self.arbol += "n" + str(aux) + "->" + "n" + str(nx) + ";\n\t"
        return aux
            
    def vListaArgumentos(self, node):
        aux = self.id()
        self.arbol += "n" + str(aux) + "[label=\"Lista Argumentos\", shape=box];\n\t"
        for i in node.lista:
            nx = i.accept(self)
            self.arbol += "n" + str(aux) + "->" + "n" + str(nx) + ";\n\t"
        return aux
    
    def vListaFunciones(self, node):
        aux = self.id()
        self.arbol += "n" + str(aux) + "[label=Lista, shape=box];\n\t"
        for i in node.lista:
            nx = i.accept(self)
            self.arbol += "n" + str(aux) + "->" + "n" + str(nx) + ";\n\t"
        return aux
            
    def vprocedimiento(self, node):
        aux = self.id()
        self.arbol += "n" + str(aux) + "[label=\"Declaracion Metodo nombre=%s\", shape=box];\n\t" % node.id.nombre
        if node.ListaArgumentos != None:
            ip = node.ListaArgumentos.accept(self)
        ib = node.bloque.accept(self)
        if node.ListaArgumentos != None:
            self.arbol += "n" + str(aux) + "->" + "n" + str(ip) + ";\n\t"
        self.arbol += "n"+str(aux) + "->" + "n" + str(ib) + ";\n\t"
        return aux
        
    def vbloque(self, node):
        aux = self.id()
        self.arbol += "n" + str(aux) + "[label=Bloque, shape=box];\n\t"
        ib = node.bloque.accept(self)
        self.arbol += "n" + str(aux) + "->" + "n" + str(ib) + ";\n\t"
        return aux
        
    def vInstruccionNormal(self, node):
        aux = self.id()
        self.arbol += "n"+str(aux) + "[label=\"Instruccion id=%s\" , shape=box];\n\t"%node.tipo
        e=node.expr.accept(self)
        self.arbol += "n" + str(aux) + "->" + "n" + str(e) + ";\n\t"
        return aux
            
    def vInstruccionSimple(self, node):
        aux = self.id()
        self.arbol+="n"+str(aux)+"[label=\"Instruccion id=%s\" , shape=box];\n\t"%node.tipo
        return aux
            
    def vLLamada(self, node):
        aux = self.id()
        self.arbol += "n" + str(aux) + "[label=llamada , shape=box];\n\t"
        i = node.id.accept(self)
        if node.parametros != None:
            p = node.parametros.accept(self)
        self.arbol += "n"+str(aux) + "->" + "n" + str(i) + ";\n\t"
        if node.parametros != None:
            self.arbol += "n" + str(aux) + "->" + "n" + str(p) + ";\n\t"
        return aux
    
    def vInstruccionSI(self, node):
        aux = self.id()
        self.arbol += "n" + str(aux) + "[label=\"Si\", shape=box];\n\t"
        expr = node.condicion.accept(self)
        b1 = node.bloque1.accept(self)
        if node.bloque2 != None:
            b2 = node.bloque2.accept(self)
        self.arbol += "n" + str(aux) + "->" + "n" + str(expr) + ";\n\t"
        self.arbol += "n" + str(aux) + "->" + "n" + str(b1) + ";\n\t"
        if node.bloque2 != None:
            self.arbol += "n" + str(aux) + "->" + "n" + str(b2) + ";\n\t"
        return aux
            
    def vCicloRepetir(self, node):
        aux = self.id()
        self.arbol += "n" + str(aux) + "[label=Ciclorepetir , shape=box];\n\t"
        e = node.expr.accept(self)
        b = node.bloque.accept(self)
        self.arbol += "n" + str(aux) + "->" + "n"+str(e) + ";\n\t"
        self.arbol += "n" + str(aux) + "->" + "n" + str(b) + ";\n\t"
        return aux
        
    def vCicloPara(self, node):
        aux = self.id()
        self.arbol += "n"+str(aux) + "[label=CicloPara , shape=box];\n\t"
        i = node.id.accept(self)
        e = node.expr1.accept(self)
        h = node.hasta.accept(self)
        inc = node.incremento.accept(self)
        b = node.bloque.accept(self)
        self.arbol += "n" + str(aux) + "->" + "n" + str(i) + ";\n\t"
        self.arbol += "n" + str(aux) + "->" + "n" + str(e) + ";\n\t"
        self.arbol += "n" + str(aux) + "->" + "n" + str(h) + ";\n\t"
        self.arbol += "n" + str(aux) + "->" + "n" + str(inc) + ";\n\t"
        self.arbol += "n" + str(aux) + "->" + "n" + str(b) + ";\n\t"
        return aux
        
    def vInstruccionMientras(self, node):
        aux = self.id()
        self.arbol += "n" + str(aux) + "[label=mientras, shape=box];\n\t"
        expr = node.condicion.accept(self)
        b1 = node.bloque.accept(self)
        self.arbol += "n" + str(aux) + "->" + "n" + str(expr) + ";\n\t"
        self.arbol += "n" + str(aux) + "->" + "n" + str(b1) + ";\n\t"
        return aux
        
    def vAsignacion(self, node):
        aux=self.id()
        self.arbol += "n" + str(aux) + "[label=\"Asignacion de variable Id=%s\", shape=box];\n\t"%node.id.nombre
        ie = node.expr.accept(self)
        self.arbol += "n" + str(aux) + "->" + "n" + str(ie) + ";\n\t"
        return aux
        
    def vRetorno(self, node):
        aux = self.id()
        self.arbol += "n" + str(aux) + "[label=Retorno, shape=box];\n\t"
        e = node.expr.accept(self)
        self.arbol += "n" + str(aux) + "->" + "n" + str(e) + ";\n\t"
        return aux
        
    def vOpBinaria(self, node):
        aux = self.id()
        self.arbol += "n" + str(aux) + "[label=\"nodoBinario %s\", shape=box];\n\t" %node.Op
        ii = node.izq.accept(self)
        id = node.der.accept(self)
        self.arbol += "n" + str(aux) + "->" + "n" + str(ii) + ";\n\t"
        self.arbol += "n" + str(aux) + "->" + "n" + str(id) + ";\n\t"
        return aux
            
    def vOpUnaria(self, node):
        aux = self.id()
        self.arbol += "n" + str(aux) + "[label=\"NodoUnario id=%s\" , shape=box];\n\t" %node.Op
        ii = node.expr.accept(self)
        self.arbol += "n" + str(aux) + "->" + "n" + str(ii) + ";\n\t"
        return aux
            
    def vId(self, node):
        aux = self.id()
        self.arbol += "n" + str(aux) + "[label=\" variable Id=%s\", shape=box];\n\t" %node.nombre
        return aux
        
    def vnumeroEntero(self, node):
        aux = self.id()
        self.arbol += "n" + str(aux) + "[label=\"Numero Entero Id=%s\", shape=box];\n\t" %node.numero
        return aux
        
    def vnumeroFlotante(self, node):
        aux = self.id()
        self.arbol += "n" + str(aux) + "[label=\"Numero Flotante Id=%s\", shape=box];\n\t" %node.numero
        return aux
        
    def vBooleano(self, node):
        aux = self.id()
        self.arbol += "n" + str(aux) + "[label=\"Booleano Id=%s\", shape=box];\n\t" %node.tipo
        return aux
    
    
#############################################################


class ASTVariables(Visitor):
    def __init__(self):
        Visitor.__init__(self)
        self.nv = 0
        self.nomvar = {}
    
    
    def vPrograma(self, node):
        node.lista.accept(self)
        
        
    def vLista(self, node):
        for i in node.lista:
            i.accept(self)
            
    def vListaInstrucciones(self, node):
        for i in node.lista:
            i.accept(self)
            
    def vListaParametros(self, node):
        for i in node.lista:
            i.accept(self)
            
    def vListaArgumentos(self, node):
        for i in node.lista:
            i.accept(self)
    
    def vListaFunciones(self, node):
        for i in node.lista:
            i.accept(self)
            
    def vprocedimiento(self, node):
        if node.ListaArgumentos != None:
            node.ListaArgumentos.accept(self)
        node.bloque.accept(self)
        self.nv = 0
        self.nomvar.clear()
        
    def vbloque(self, node):
        node.bloque.accept(self)
        
    def vInstruccionNormal(self, node):
        node.expr.accept(self)
            
    def vLLamada(self, node):
        if node.parametros != None:
            node.parametros.accept(self)
    
    def vInstruccionSI(self, node):
        node.condicion.accept(self)
        node.bloque1.accept(self)
        if node.bloque2 != None:
            node.bloque2.accept(self)
            
    def vCicloRepetir(self, node):
        node.expr.accept(self)
        node.bloque.accept(self)
        
    def vCicloPara(self, node):
        node.id.accept(self)
        node.expr1.accept(self)
        node.hasta.accept(self)
        node.incremento.accept(self)
        node.bloque.accept(self)
        
    def vInstruccionMientras(self, node):
        node.condicion.accept(self)
        node.bloque.accept(self)
        
    def vAsignacion(self, node):
        node.id.accept(self)
        node.expr.accept(self)
        
    def vRetorno(self, node):
        node.expr.accept(self)
        
        
    def vOpBinaria(self, node):
        node.izq.accept(self)
        node.der.accept(self)
            
    def vOpUnaria(self, node):
        node.expr.accept(self)
            
    def vId(self, node):
        if self.nomvar.has_key(node.nombre):
            node.nombre = self.nomvar[node.nombre]
        else:
            self.nomvar[node.nombre] = self.nv
            node.nombre = self.nv
            self.nv += 1
        
